package com.ruoyi.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.*;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.user.constant.LoginConstant;
import com.ruoyi.user.domain.TbUser;
import com.ruoyi.user.service.TbUserService;
import com.ruoyi.user.mapper.TbUserMapper;
import com.ruoyi.user.utils.TokenUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
        implements TbUserService {


    @Autowired
    private TbUserMapper tbUserMapper;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Value("${user.tokenKey}")
    private String tokenKey;

    @Override
    public R<UserVo> getUserById(IdVo idVo) {

        TbUser tbUser = tbUserMapper.selectById(idVo.getId());

        tbUser.setUserPass(null);
        tbUser.setIdNumber(null);
        tbUser.setRealName(null);
        tbUser.setBalance(null);

        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(tbUser, userVo);
        return R.ok(userVo);
    }

    @Override
    public AjaxResult selectAllUserByCondition(UserQueryCondition userQueryCondition) {

        LambdaQueryWrapper<TbUser> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.like(StringUtils.isNotEmpty(userQueryCondition.getUserName()), TbUser::getUserName, userQueryCondition.getUserName())
                .or().eq(StringUtils.isNotEmpty(userQueryCondition.getEmail()), TbUser::getUserEmail, userQueryCondition.getEmail())
                .or().eq(StringUtils.isNotEmpty(userQueryCondition.getMobile()), TbUser::getUserMobile, userQueryCondition.getMobile())
                .or().like(StringUtils.isNotEmpty(userQueryCondition.getRealName()), TbUser::getRealName, userQueryCondition.getRealName());

        List<TbUser> tbUserList = tbUserMapper.selectList(queryWrapper);

        List<UserVo> userVoList = tbUserList.stream().map(tbUser -> {
            tbUser.setUserPass(null);
            tbUser.setIdNumber(null);
            tbUser.setRealName(null);
            tbUser.setBalance(null);
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(tbUser, userVo);
            return userVo;
        }).collect(Collectors.toList());

        return AjaxResult.warn("查询用户可能为空", userVoList);
    }

    @Override
    public R addUser(UserVo userVo) {
        LambdaQueryWrapper<TbUser> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(StringUtils.isNotEmpty(userVo.getUserMobile()), TbUser::getUserMobile, userVo.getUserMobile());

        TbUser tbUser = tbUserMapper.selectOne(queryWrapper);

        if (Objects.nonNull(tbUser))
            return R.fail("手机号已被注册");


        BeanUtils.copyProperties(userVo, tbUser = new TbUser());
        tbUser.setUserName("botian" + userVo.getUserMobile());
        tbUser.setCreateBy(userVo.getUserName());
        tbUser.setUpdateBy(userVo.getUserName());
        tbUser.setUserPass(defaultPassword());

        int insert = tbUserMapper.insert(tbUser);

        return insert > 0 ? R.ok("添加成功") : R.fail("持久层错误,添加失败");
    }

    @Override
    @Transactional
    public R deleteUserById(IdVo idVo) {

        TbUser tbUser = tbUserMapper.selectById(idVo.getId());

        if (Objects.isNull(tbUser))
            return R.fail("指定删除的用户不存在");


        tbUser.setUpdateBy(tbUser.getUserName());
        tbUser.setUpdateTime(null);

        tbUserMapper.updateById(tbUser);
        int delete = tbUserMapper.deleteById(idVo.getId());

        return delete > 0 ? R.ok("删除成功") : R.fail("持久层错误,删除失败");
    }

    @Override
    public R updateUserForCondition(UserUpdateCondition userUpdateCondition) {

        TbUser tbUser = tbUserMapper.selectById(userUpdateCondition.getUserId());

        if (Objects.isNull(tbUser))
            return R.fail("指定修改的用户不存在");


        BeanUtils.copyProperties(userUpdateCondition,tbUser);
        tbUser.setUpdateBy(tbUser.getUserName());
        tbUser.setUpdateTime(null);

        int update = tbUserMapper.updateById(tbUser);
        return update > 0 ? R.ok("修改成功") : R.fail("持久层错误,修改失败");
    }

    @Override
    public R verifyCodeLogin(LoginVo loginVo) {

        String verifyCode = (String) redisTemplate.opsForValue().get(LoginConstant.LOGIN_MOBILE_VERIFY_CODE + ":" + LoginConstant.LOGIN_MOBILE_VERIFY_CODE + loginVo.getMobile());
        boolean equals = loginVo.getVerifyCode().equals(verifyCode);
        System.out.println(equals);
        if (!equals) {
            return R.fail("验证码错误");
        }
        TbUser tbUser = tbUserMapper.selectOne(
                new LambdaQueryWrapper<TbUser>().eq(TbUser::getUserMobile, loginVo.getMobile()).last("limit 1")
        );
        if (Objects.isNull(tbUser)) {
            return R.fail("用户不存在");
        }
        return storeLoginInfo(tbUser);
    }

    private R storeLoginInfo(TbUser tbUser) {
        String token = TokenUtils.token()
                .setKey(tokenKey)
                .setClaim("userId", tbUser.getUserId() + "")
                .setClaim("userName", tbUser.getUserName()).makeToken();
        redisTemplate.opsForValue().set(LoginConstant.LOGIN_TOKEN + ":" + token + tbUser.getUserId(), token, 30, TimeUnit.MINUTES);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(tbUser, userVo);
        userVo.setToken(token);
        userVo.setUserPass(null);
        return R.ok(userVo);
    }

    static final private String defaultPassword() {
        return BCrypt.hashpw("123456", BCrypt.gensalt());
    }

}




